import 'dart:async';
import 'dart:typed_data';

import 'package:plugin_platform_interface/plugin_platform_interface.dart';

import 'jm_usb_method_channel.dart';
import 'model/model.dart';

abstract class JmUsbPlatform extends PlatformInterface {
  /// Constructs a JmUsbPlatform.
  JmUsbPlatform() : super(token: _token);

  static final Object _token = Object();

  static JmUsbPlatform _instance = MethodChannelJmUsb();

  /// The default instance of [JmUsbPlatform] to use.
  ///
  /// Defaults to [MethodChannelJmUsb].
  static JmUsbPlatform get instance => _instance;

  /// Platform-specific implementations should set this with their own
  /// platform-specific class that extends [JmUsbPlatform] when
  /// they register themselves.
  static set instance(JmUsbPlatform instance) {
    PlatformInterface.verifyToken(instance, _token);
    _instance = instance;
  }

  Stream<bool> get connectStream;
  Stream<Uint8List> get dataReceivedStream;
  Stream<int> get dataLengthStream;

  Future<bool> init();

  Future<void> exit();

  Future<bool> quickConnectDevice(
    UsbDevice usbDevice, {
    int configurationIndex = 0,
    int interfaceIndex = 0,
    int? endpointInIndex,
    int? endpointOutIndex,
  });

  Future<bool> quickConnectAccessory();

  Future<int> quickGetFileDescriptor(
    UsbDevice usbDevice, {
    int configurationIndex = 0,
    int interfaceIndex = 0,
    int? endpointInIndex,
    int? endpointOutIndex,
  });

  Future<List<UsbDevice>> getDeviceList();

  Future<List<UsbAccessory>> getAccessoryList();

  Future<List<UsbDeviceDescription>> getDevicesWithDescription(
      {bool requestPermission = true});

  Future<UsbDeviceDescription> getDeviceDescription(UsbDevice usbDevice,
      {bool requestPermission = true});

  Future<bool> hasPermission(UsbDevice usbDevice);

  Future<bool> requestPermission(UsbDevice usbDevice);

  Future<String> getSerialNumber();

  Future<int> getFileDescriptor();

  Future<bool> openDevice(UsbDevice usbDevice);

  Future<void> closeDevice();

  Future<UsbConfiguration> getConfiguration(int index);

  Future<bool> setConfiguration(UsbConfiguration config);

  Future<bool> claimInterface(UsbInterface intf);

  Future<bool> detachKernelDriver(UsbInterface intf);

  Future<bool> releaseInterface(UsbInterface intf);

  Future<Uint8List> bulkTransferIn(
      UsbEndpoint endpoint, int maxLength, int timeout);

  Future<int> bulkTransferOut(
      UsbEndpoint endpoint, Uint8List data, int timeout);

  Future<bool> controlTransfer({
    int requestType = 0,
    int request = 0,
    int value = 0,
    int index = 0,
    Uint8List? data,
  });

  Future<bool> writeData(Uint8List data, int timeout);

  Future<Uint8List?> readData(int maxLength, int timeout);

  Future<bool> accessoryWriteData(Uint8List data, int timeout);

  Future<Uint8List?> accessoryReadData(int maxLength, int timeout);

  Future<void> startDataListening({
    int type = 0,
    int accumulatedBufferSize = 0,
    int requestCount = 8,
    int bufferSize = 16384,
  });

  Future<void> stopDataListening();

  Future<void> setAutoDetachKernelDriver(bool enable);
}
